{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程池任务队列配置"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "任务队列上限阈值\n",
    "\n",
    "- 默认值设置：任务队列数量上限阈值默认设置为1024，作为任务队列大小的基准值\n",
    "- 可配置性设计：通过`setTaskQueMaxThreshHold`接口允许用户自定义该阈值，以适应不同硬件资源场景\n",
    "- 设计考量：考虑到服务器硬件资源差异，高配置服务器可能需要更大的任务队列容量\n",
    "- 阈值设置方法：提供`void setTaskQueMaxThreshHold(int threshhold)`方法用于动态调整任务队列上限\n",
    "- 线程安全机制：使用`std::mutex`保护任务队列，配合`std::condition_variable`实现线程间通信"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程池核心接口\n",
    "- 模式设置：通过`setMode`方法支持`fixed`(默认)和`cached`两种线程池工作模式\n",
    "- 启动控制：`start`方法用于初始化并启动线程池中的所有工作线程\n",
    "- 任务提交：`submitTask`接口采用`std::shared_ptr<Task>`智能指针管理任务生命周期\n",
    "- 任务存储方式：使用`std::queue<std::shared_ptr<Task>>`作为线程安全的任务队列容器\n",
    "- 原子计数器：通过`std::atomic_int`原子变量准确统计当前任务数量\n",
    "- 条件变量：`notFull_`和`notEmpty_`条件变量分别控制队列的写入和读取操作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 智能指针封装的任务"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 任务封装方式：使用智能指针`std::shared_ptr<Task>`封装任务对象，确保任务对象的生命周期管理\n",
    "- 自动内存管理：任务对象通过new创建后由智能指针自动管理，无需手动释放内存\n",
    "- 任务持有机制：线程池会持续持有任务对象直到任务完成，防止任务中途被意外释放"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程池核心组件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "任务队列管理\n",
    "\n",
    "- 队列阈值：通过`setTaskQueMaxThreshHold`方法设置任务队列最大阈值（默认1024）\n",
    "- 线程安全机制：\n",
    "  - 使用`std::mutex`保证任务队列的线程安全\n",
    "  - 通过`std::condition_variable`实现生产者-消费者模型\n",
    "    - `notFull_`：表示任务队列未满的条件变量\n",
    "    - `notEmpty_`：表示任务队列非空的条件变量\n",
    "- 原子计数器：使用`std::atomic_int taskSize_实`时统计当前任务数量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程池接口设计\n",
    "\n",
    "- 核心方法：\n",
    "  - `submitTask()`：提交智能指针封装的任务到队列\n",
    "  - `start()`：启动线程池工作\n",
    "  - `setMode()`：设置线程池工作模式（`fixed/cached`）\n",
    "- 资源管理：\n",
    "  - `ThreadPool()`：构造函数初始化线程列表\n",
    "  - `~ThreadPool()`：析构函数负责资源清理\n",
    "- 禁用拷贝：线程池对象禁止拷贝构造和赋值操作，保证资源唯一性"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程池实现细节"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程池实现细节\n",
    "\n",
    "- 线程管理：\n",
    "  - `threads_`：存储线程指针的`vector`容器\n",
    "  - `initThreadSize_`：记录初始线程数量\n",
    "- 任务队列：\n",
    "  - `taskQue_`：使用`std::queue`存储待处理任务\n",
    "  - `taskQueMaxThreshHold_`：队列容量上限阈值\n",
    "- 同步机制：\n",
    "  - `taskQueMtx_`：保护任务队列的互斥锁\n",
    "  - 双条件变量设计实现高效线程通信"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程池的使用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 对象创建：需要使用时直接定义线程池对象，禁止进行拷贝构造或赋值操作\n",
    "- 工作模式：支持`fixed`（默认）和`cached`（动态增长）两种线程池模式\n",
    "- 任务提交：通过`submitTask`方法提交具体任务，返回`Result`对象用于获取处理结果\n",
    "- 结果获取：使用`result.get().Cast<结果类型>()`方法线程安全地获取任务执行结果"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程池的构造"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "成员变量初始化\n",
    "\n",
    "- 初始化原则：成员变量尽量在初始化列表中进行初始化\n",
    "- 核心数量：默认初始线程数设为4（测试用），实际应使用CPU核心数\n",
    "- 任务队列：`taskSize_`初始值为0，`taskQueMaxThreshHold_`默认1024\n",
    "- 常量定义：使用`TASK_MAX_THRESHHOLD`常量代替魔数1024"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "关键成员说明\n",
    "\n",
    "- 线程管理：使用`std::vector<Thread*> threads_`维护线程列表\n",
    "- 任务队列：`std::queue<std::shared_ptr<Task>>`实现任务队列\n",
    "- 线程安全：通过`std::mutex`和`std::condition_variable`保证队列安全\n",
    "- 模式控制：`PoolMode poolMode_`记录当前工作模式（fixed/cached）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "禁用拷贝控制\n",
    "\n",
    "- 设计原因：包含容器、锁、条件变量等复杂成员，拷贝会导致问题\n",
    "- 实现方式：使用`=delete`显式删除拷贝构造函数和赋值运算符\n",
    "- 使用建议：始终通过创建新对象的方式使用线程池"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程池的析构"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 析构必要性：即使当前没有资源需要释放，只要存在构造函数就必须显式定义析构函数。这是C++编程规范的要求，为将来可能增加的资源管理功能预留接口。\n",
    "- 编程态度体现：显式写出析构函数是一种良好的编程态度，表明开发者对资源管理的重视程度。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程池配置方法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "工作模式设置\n",
    "\n",
    "- 实现方式：通过`setMode(PoolMode mode)`方法直接修改成员变量`poolMode_`的值，实现线程池工作模式的动态切换。\n",
    "- 参数传递：采用值传递方式接收模式参数，内部实现为简单的赋值操作`poolMode_ = mode`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程数量设置\n",
    "\n",
    "- 成员变量：`initThreadSize_`存储初始线程数量，通过`setInitThreadSize(int size)`方法进行修改。\n",
    "- 原子操作：任务数量`taskSize_`使用`std::atomic_int`类型保证线程安全。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "任务队列阈值设置\n",
    "\n",
    "- 阈值管理：通过`setTaskQueMaxThreshHold(int threshhold)`方法设置任务队列上限阈值，赋值给成员变量`taskQueMaxThreshHold_`。\n",
    "- 线程安全：任务队列使用`std::mutex`和`std::condition_variable`保证线程安全操作。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 通用设计原则"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- `set`方法特点：配置类方法通常实现简单，主要完成成员变量的赋值操作，但需要考虑线程安全性。\n",
    "- 资源管理规范：构造/析构函数应成对出现，即使当前不需要资源释放也应保留析构函数声明。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 提交异步任务 "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "项目介绍与线程池模式\n",
    "\n",
    "- 工作模式选择：线程池提供两种模式设置：固定模式(fixed)和缓存模式(cached)，通过`pool.setMode()`方法进行配置\n",
    "- 动态线程管理：在cached模式下，线程数量会根据任务量动态增长，但会设置上限阈值，空闲线程超过60秒会被自动回收\n",
    "- 默认配置：线程池创建时默认采用固定模式，线程数量根据CPU核心数指定"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程池启动与任务提交\n",
    "\n",
    "- 启动流程：必须通过`start()`方法显式启动线程池后，才能接收外部任务提交\n",
    "- 初始化优化：将初始线程数参数合并到`start()`方法中，简化接口调用\n",
    "- 默认线程数：建议使用CPU核心数作为默认值，可通过`std::thread::hardware_concurrency()`获取\n",
    "- 任务队列阈值：设置`taskQueMaxThreshHold_`参数限制任务队列最大容量，防止资源耗尽"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程池接口简化讨论 \n",
    "\n",
    "- 接口精简原则：合并`setInitThreadSize()`方法到`start()`，减少用户需要记忆的接口数量\n",
    "- 默认值设置：初始化参数只需设置一次，建议在构造函数中完成\n",
    "- 关键接口保留：必须保留`setMode()`和`setTaskQueMaxThreshHold()`等核心配置接口"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接口设计与用户体验\n",
    "\n",
    "- 设计理念：接口应当简单清晰，避免给用户造成认知负担\n",
    "- 必要接口：保留模式设置、阈值设置、任务提交和启动四个核心接口\n",
    "- 使用流程：明确调用顺序：先配置模式参数→设置队列阈值→启动线程池→最后提交任务\n",
    "- 实现细节：采用C++17的`any`和C++20的`semaphore`特性，保证线程安全"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 开启线程池"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "start方法参数解析\n",
    "\n",
    "- 参数灵活性: `start`方法参数`initThreadSize`为用户可选参数，不传时使用默认线程数量，传入时使用用户指定值\n",
    "- 方法必要性: `start`方法是使用线程池必须调用的方法，用于初始化线程池工作状态"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程数量初始化\n",
    "\n",
    "- 成员变量赋值: 在`start`方法中通过`initThreadSize_ = initThreadSize`完成线程数量初始化\n",
    "- 构造函数设计: 构造函数中线程数量可初始化为`0`，因为实际值会在`start`方法中被覆盖"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "创建线程对象\n",
    "\n",
    "- 创建时机: 在记录初始线程数量后，需要立即创建对应数量的线程对象\n",
    "- 实现方式: 使用`for`循环逐个创建线程对象，循环次数为`initThreadSize_`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程对象存储方式\n",
    "\n",
    "- 容器选择: 使用`std::vector<Thread*> threads_`存储线程对象指针\n",
    "- 创建方法: 通过`new Thread()`创建线程对象，并使用`emplace_back`添加到`vector`中"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程启动与任务执行\n",
    "\n",
    "- 两阶段启动:\n",
    "  - 第一阶段：集中创建所有线程对象\n",
    "  - 第二阶段：统一启动所有线程（通过调用每个线程的start方法）\n",
    "- 公平性保证: 这种设计可以保证线程启动的公平性，避免先创建的线程总是先执行"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程函数与任务队列\n",
    "\n",
    "- 线程函数作用: 每个线程执行相同的线程函数，不断检查任务队列并执行任务\n",
    "- 共享资源管理:\n",
    "  - 使用`std::mutex taskQueMtx_`保证任务队列线程安全\n",
    "  - 通过`std::condition_variable notFull_`和`notEmpty_`实现生产者-消费者模型\n",
    "- 任务处理流程: 线程从任务队列获取任务后，调用任务的`run`方法执行具体操作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程函数的定义"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程函数的定义\n",
    "\n",
    "- 定义位置问题: 将线程函数直接定义在线程类内部不合适，因为会导致访问线程池成员变量困难。\n",
    "- 访问限制: 线程函数需要访问线程池的私有成员变量，但定义在`Thread`类中会导致访问权限问题。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程函数访问变量问题\n",
    "\n",
    "- 关键变量: 线程池包含重要成员变量：\n",
    "  - `taskQueMaxThreshHold_`：任务队列数量上限阈值\n",
    "  - `notFull_/notEmpty_`：条件变量表示队列状态\n",
    "  - `taskQueMtx_`：保证队列线程安全的互斥锁\n",
    "- 访问困境: 这些私有变量无法被外部线程函数直接访问。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "全局函数的可行性讨论\n",
    "\n",
    "全局方案缺陷:\n",
    "- 虽然可以定义全局线程函数\n",
    "- 但无法访问线程池对象的私有成员变量\n",
    "- 违背面向对象封装原则"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程池私有成员变量的访问 \n",
    "\n",
    "- OOP解决方案:\n",
    "  - 采用面向对象方法\n",
    "  - 将线程函数定义为线程池的成员函数\n",
    "  - 自然获得访问私有变量的权限"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程函数的定义位置\n",
    "\n",
    "最佳实践:\n",
    "- 在`ThreadPool`类中定义`threadFunc`成员函数\n",
    "- 作为线程实际执行的函数体\n",
    "- 完美解决变量访问问题"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程函数的执行内容\n",
    "\n",
    "执行逻辑:\n",
    "\n",
    "- 线程池创建线程时指定执行`threadFunc`\n",
    "- 该函数包含线程的主要工作逻辑\n",
    "- 可直接操作线程池所有成员变量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程函数的命名 \n",
    "\n",
    "命名规范:\n",
    "\n",
    "- 使用`threadFunc`作为标准命名\n",
    "- 明确表示其线程执行函数的用途\n",
    "- 在`ThreadPool`类中定义为`private`成员"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "线程函数与线程对象的关联\n",
    "\n",
    "- 关联机制:\n",
    "  - 通过线程构造函数传递可调用对象\n",
    "  - 使用`std::bind`绑定成员函数\n",
    "  - 需要掌握C++高级特性才能完全理解实现\n",
    "- 关键点:\n",
    "  - 线程对象必须能访问线程池的成员函数\n",
    "  - 需要正确处理`this`指针的绑定问题"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线程对象绑定"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 构造函数初始化:\n",
    "  - `taskSize_`初始化为`0`表示初始无任务\n",
    "  - `taskQueMaxThreshHold_`设置为`TASK_MAX_THRESHHOLD`常量值\n",
    "  - `poolMode_`默认设为固定模式`MODE_FIXED`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 绑定器使用原理:\n",
    "  - 通过`std::bind`将线程函数`threadFunc`与线程池对象`this`指针绑定\n",
    "  - 关键设计：线程函数需要访问线程池成员变量，因此必须绑定线程池对象\n",
    "  - 实现方式：`threads_.emplace_back(new Thread(std::bind(&ThreadPool::threadFunc, this)))`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 线程启动过程:\n",
    "  - 遍历线程向量`threads_`调用每个线程的`start()`方法\n",
    "  - `start()`方法实际执行绑定的`threadFunc`函数\n",
    "  - 设计优势：线程创建与执行逻辑分离，通过绑定器实现灵活调用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 核心成员变量:\n",
    "  - `threads_`：存储线程指针的向量容器\n",
    "  - `taskQue_`：任务队列使用`std::shared_ptr<Task>`智能指针\n",
    "  - 线程安全机制：包含互斥锁`taskQueMtx_`和条件变量`notFull_/notEmpty_`\n",
    "  - 原子变量`taskSize_`保证任务计数线程安全"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 设计要点:\n",
    "  - 绑定必要性：线程函数需要访问线程池的成员变量（如任务队列、互斥锁等）\n",
    "  - 资源管理：使用智能指针管理任务对象生命周期\n",
    "  - 模式切换：通过`poolMode_`支持不同工作模式（如固定模式/动态模式）\n",
    "  - 线程安全：采用原子变量和条件变量实现线程间协调"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 线程函数特性:\n",
    "  - 声明为私有成员函数`void threadFunc()`\n",
    "  - 实际包含线程的主要工作逻辑（获取任务、执行任务等）\n",
    "  - 通过绑定器将对象上下文传递给线程函数"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "name": "C++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
